package com.kelai.service.impl;

import com.google.common.base.Joiner;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.kelai.callback.IdCallback;
import com.kelai.common.IDistribution;
import com.kelai.common.IRepository;
import com.kelai.common.constants.DeviceStatusEnum;
import com.kelai.common.constants.ShopStatusEnum;
import com.kelai.common.constants.WebAppConstants;
import com.kelai.common.exception.BreezeeException;
import com.kelai.common.exception.EntityNotFoundException;
import com.kelai.domain.*;
import com.kelai.repository.*;
import com.kelai.resource.impl.DefaultDeviceResource;
import com.kelai.service.ICustomerService;
import com.kelai.service.IDeviceDataService;
import com.kelai.service.IDeviceService;
import com.kelai.service.ISissService;
import com.kelai.utils.BreezeeUtils;
import com.kelai.utils.ContextUtil;
import com.kelai.utils.SystemTool;
import javafx.util.Callback;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.olap4j.*;
import org.olap4j.metadata.Member;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.sql.DriverManager;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 设备数据服务
 * Created by Silence on 2016/11/26.
 */
@SuppressWarnings("unchecked")
@Service("deviceDataService")
public class DefaultDeviceDataService implements IDeviceDataService {

    private final static Logger logger = LoggerFactory.getLogger(DefaultDeviceDataService.class);
    private final static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

    private final IDeviceDataRepository deviceDataRepository;

    private final IDeviceDayDataRepository deviceDayDataRepository;

    private final IDeviceDataDayRepository deviceDataDayRepository; // bi

    private final IErrorMsgRepository errorMsgRepository;

    private final JdbcTemplate jdbcTemplate;


    @Resource
    private IDeviceService deviceService;
    @Resource
    private ICustomerService customerService;
    @Resource
    private ISissService sissService;
    @Resource
    private IdCallback idCallback;

    @Autowired
    public DefaultDeviceDataService(IDeviceDataRepository deviceDataRepository,
                                    IDeviceDayDataRepository deviceDayDataRepository,
                                    IDeviceDataDayRepository deviceDataDayRepository,
                                    IErrorMsgRepository errorMsgRepository,
                                    JdbcTemplate jdbcTemplate) {
        this.deviceDataRepository = deviceDataRepository;
        this.deviceDayDataRepository = deviceDayDataRepository;
        this.deviceDataDayRepository = deviceDataDayRepository;
        this.errorMsgRepository = errorMsgRepository;
        this.jdbcTemplate = jdbcTemplate;
    }

    @Override
    public IRepository<DeviceDataEntity> getRepository() {
        return deviceDataRepository;
    }


    @Override
    public DeviceDataEntity saveInfo(DeviceDataEntity r,
                                     Callback<DeviceDataEntity, Object>... callback)
            throws BreezeeException {
//        if (r.getProperties().get("_repeat") != null && r.getProperties().get("_repeat").toString().equals("0")) {
        if (deviceDataRepository.findByCode(r.getCode()) == null) {
            String id = r.getSn() + "-" + r.getHappenTime().toString().substring(0, 8);
            //TODO DeviceDayDataEntity现在仅作某些场景下页面展示用的DTO 所以不用存储
            /*DeviceDayDataEntity dayData = deviceDayDataRepository.findByCode(id);
            if (dayData != null) {
                dayData.setDxin( (dayData.getDxin()==null? 0 :dayData.getDxin())  + (r.getDxin()==null? 0 : r.getDxin()));
                dayData.setDxout((dayData.getDxout()==null? 0 :dayData.getDxout())  + (r.getDxout()==null? 0 : r.getDxout()));
            } else {
                dayData = new DeviceDayDataEntity();
                dayData.setCode(id);
                dayData.setName(r.getSn());
                dayData.setDxin(r.getDxin());
                dayData.setDxout(r.getDxout());
                dayData.setHappenTime(Long.parseLong(LocalDate.now().toString().replaceAll("-", "")));
                dayData.setCustomer(r.getCustomer());
                dayData.setCustomerId(r.getCustomerId());
            }
            deviceDayDataRepository.saveEntity(dayData, new Callback[]{idCallback});*/
        } else {
            //针对重复数据，如何处理？1. 获取之前的数据与当前数据的差值，进行求和计算即可。这个和值，可以从前端传递过来
        }
        Map<String, IDistribution> m = ContextUtil.current.getBeansOfType(IDistribution.class);
        List<Callback> l = new ArrayList<>();
        l.add(idCallback);
        if (m != null) {
            m.values().forEach(a -> {
                l.add((Callback) a);
            });
        }
        Callback[] cc = new Callback[l.size()];
        return deviceDataRepository.saveEntity(r, l.toArray(cc));
    }

    @Override
    public Map<String, Object> sumTodayData(String code) {

        LocalDate date = LocalDate.now();
        String startDate = date.format(DateTimeFormatter.BASIC_ISO_DATE) + "000000";
        String endDate = date.format(DateTimeFormatter.BASIC_ISO_DATE) + "235959";

        String sql = " select sum(dxin) dxin,sum(dxout) dxout from t_device_data " +
                " where sn = '" + code + "'" +
                " and happen_time > '" + startDate + "'" +
                " and happen_time < '" + endDate + "'";
        Map<String, Object> map = jdbcTemplate.queryForMap(sql);
        return map;
    }

    /**
     * 将老设备数据插入我们的新设备表，临时使用一次
     * 将t_condition_info , t_gprs_register老设备表数据插入到t_device表
     */
    @Override
    public void syncOldData() {

        logger.info("同步老设备数据开始...");

        StringBuilder strBuilder = new StringBuilder("");
        strBuilder.append(" select ");
        strBuilder.append(" device.id, "); //设备code
        strBuilder.append(" device.info, "); //设备位置
        strBuilder.append(" device.module_no, "); //门店code
        strBuilder.append(" shop.Last_ScanTime, "); //最后联机时间
        strBuilder.append(" device.losefocus, "); //是否失焦
        strBuilder.append(" shop.lastbat, "); //剩余电量
        strBuilder.append(" shop.ischarge, "); //是否充电
        strBuilder.append(" device.direction "); //安装方向
        strBuilder.append(" from [shopcusrec].[dbo].t_condition_info device,[shopcusrec].[dbo].[t_gprs_register] shop ");
        strBuilder.append(" where device.module_no = shop.module_no ");

        jdbcTemplate.queryForList(strBuilder.toString()).forEach(item -> {
            try {
                String shopCode = item.get("module_no").toString();
                CustomerEntity customer = customerService.findByCode(shopCode);
                String deviceId = String.valueOf(item.get("id").toString());

                DeviceEntity condition = new DeviceEntity();
                condition.getProperties().put("id", deviceId);
                List<DeviceEntity> deviceList = deviceService.listAll(condition);
                if (deviceList == null || deviceList.size() == 0) {
                    DeviceEntity device = new DeviceEntity();
//                  device.setId(deviceId);
                    device.setCode(deviceId);
                    device.setName(deviceId);
                    device.setStatus(0);
                    //device.setBattery(item.get("lastbat") == null ? 0 : Integer.valueOf(item.get("lastbat").toString()));
                    device.setCharge(item.get("ischarge") == null ? 0 : Integer.valueOf(item.get("ischarge").toString()));
                    //device.setCommandType();
                    //device.setCounterDisplay();
                    //device.setDeviceTime();
                    //device.setFixTimeUpload();
                    device.setFocus(item.get("losefocus") == null ? 0 : Integer.valueOf(item.get("losefocus").toString()));
                    //device.setIpAddress();
                    device.setLastReceiveTime(item.get("Last_ScanTime") == null ? 0 : BreezeeUtils.DATE_FORMAT_LONG.parse(item.get("Last_ScanTime").toString()).getTime());
                    //device.setOpenTime();
                    device.setPosition(String.valueOf(item.get("info")));
                    device.setRecordCycle(5);
                    device.setSpeed(0);
                    device.setType("dtk1");
                    device.setUploadCycle(10);
                    device.setUploadPeriod(10);
                    device.setVoltage(item.get("lastbat") == null ? 0 : Integer.valueOf(item.get("lastbat").toString()));
                    device.setCustomer(customer);
                    device.setDirection(item.get("direction") == null ? 0 : Integer.valueOf(item.get("direction").toString()));
                    device.setCustomerId("9236b103947f4f71b261bcf958286b2c");
                    device.setRemoteHost("unknown");
                    device.setRecordPeriod(5);
                    device.setLevel("5");
                    device.setRemark("MANU");
                    deviceService.saveInfo(device, new Callback[]{idCallback});
                }
            } catch (ParseException e) {
                e.printStackTrace();
            }
        });

        logger.info("同步老设备数据结束...");
    }


    /**
     * 从BI中抽取数据,提供给思讯
     * 1 找出所有店铺
     * 2 在t_siss_data表里找相关数据，找时间最近的记录 为开始时间，当天为截至时间，去BI取数据。
     * 若没有则去t_device_data里找时间最远记录，一直取到今天为止。
     */
    @Override
    public void statisticsSiss(String shopId, String shopCode) {

        logger.info("--start statisticsSiss job-- shopId:" + shopId + " | shopCode:" + shopCode);
        OlapConnection con = null;
        OlapWrapper wrapper = null;
        OlapConnection olapConnection = null;
        OlapStatement stmt = null;
        CellSet cellSet = null;
        try {
            Class.forName("org.olap4j.driver.xmla.XmlaOlap4jDriver");
            con = (OlapConnection) DriverManager.getConnection("jdbc:xmla:Server=http://" + WebAppConstants.BI_LINK_IP + "/MDKL/msmdpump.dll;Catalog=" + WebAppConstants.BI_LINK_NAME);
            wrapper = (OlapWrapper) con;
            olapConnection = wrapper.unwrap(OlapConnection.class);

            String sqlSiss = " select max(datetime) from T_SISS_DATA where shop_id = '" + shopId + "'";
            String happenTime = jdbcTemplate.queryForObject(sqlSiss, String.class);
            if (StringUtils.isEmpty(happenTime)) {
//                    String sqlDeviceData = " select min(happen_time) from t_device_data where cus_id = '"+shopId+"'";
//                    happenTime = jdbcTemplate.queryForObject(sqlDeviceData, String.class);
//                    if(StringUtils.isEmpty(happenTime)){
                happenTime = "20170816000000";
//                    }
            }
            String startDate = happenTime.substring(0, 4) + "-" + happenTime.substring(4, 6) + "-" + happenTime.substring(6, 8);
            String endDate = LocalDate.now().toString();
            logger.info("startDate:" + startDate);
            logger.info("endDate:" + endDate);

            StringBuffer strBuffer = new StringBuffer();
            strBuffer.append(" ");
            strBuffer.append(" SELECT NON EMPTY { [Measures].[进], [Measures].[出] } ON 0, ");
            strBuffer.append("  {  [组织].[组织ID].[组织ID].ALLMEMBERS *  ");
            strBuffer.append(" [时间].[年].[年].ALLMEMBERS * ");
            strBuffer.append(" [时间].[月].[月].ALLMEMBERS *  ");
            strBuffer.append(" [时间].[日].[日].ALLMEMBERS * ");
            strBuffer.append(" [时间].[小时].[小时].ALLMEMBERS } on 1 ");
            strBuffer.append(" FROM ( SELECT ( { [时间].[年月日小时].[小时].&[" + startDate + "T00:00:00]:[时间].[年月日小时].[小时].&[" + endDate + "T00:00:00]},{ ");
            strBuffer.append("  [组织].[组织层次].&[" + shopId + "]  ");
            strBuffer.append(" } ) ON COLUMNS ");
            strBuffer.append(" FROM [客流]) ");


            stmt = olapConnection.createStatement();

            cellSet = stmt.executeOlapQuery(strBuffer.toString());

            for (Position rowPos : cellSet.getAxes().get(1)) {
                String s = "";
                for (Member member : rowPos.getMembers()) {
                    s += member.getCaption() + "*";
                }
                for (Position colPos : cellSet.getAxes().get(0)) {
                    Cell cell = cellSet.getCell(colPos, rowPos);
                    s += cell.getFormattedValue() + "*";
                }
                String[] ss = s.split("\\*");

                logger.info(ss[0] + " || " + ss[1] + " || " + ss[2] + " || " + ss[3] + " || " + ss[4]);
                String id = ss[0] + "-" + ss[1] + ss[2] + ss[3] + ss[4];
                SissDataEntity sde = null;
                try {
                    sde = sissService.findByCode(id);
                } catch (EntityNotFoundException ignored) {
                }
                if (sde == null) {
                    sde = new SissDataEntity();
                }
//                    sde.setId(id);
                sde.setCode(id);
                sde.setShopId(shopId);
                sde.setShopCode(shopCode);
                sde.setDatetime(ss[1] + ss[2] + ss[3] + ss[4] + "0000");
                sde.setConsumeFlag("0");
                if (ss.length < 6) {
                    sde.setCnt("0");
                } else {
                    sde.setCnt(ss[5]);
                    sissService.saveInfo(sde, new Callback[]{idCallback});
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (cellSet != null) {
                    cellSet.close();
                }
                if (stmt != null) {
                    stmt.close();
                }
                if (olapConnection != null) {
                    olapConnection.close();
                }
                if (con != null) {
                    con.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        logger.info("--end statisticsSiss job-- ");

    }

    /**
     * 初始化数据
     */
    @Override
    public void initDataForSsis(String shopId, String shopCode) {

        LocalDate start = LocalDate.parse("2017-08-15", DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        LocalDate end = LocalDate.parse("2017-08-16", DateTimeFormatter.ofPattern("yyyy-MM-dd"));

        Boolean execFlag = true;
        logger.info("--start statisticsSiss job-- shopId:" + shopId + " | shopCode:" + shopCode);
        while (execFlag) {

            LocalDate endDate = end;
            LocalDate startDate = endDate.minusDays(1);


            logger.info("--startDate :" + startDate + " | endDate :" + endDate);
            OlapConnection con = null;
            OlapWrapper wrapper = null;
            OlapConnection olapConnection = null;
            OlapStatement stmt = null;
            CellSet cellSet = null;
            try {
                Class.forName("org.olap4j.driver.xmla.XmlaOlap4jDriver");
                con = (OlapConnection) DriverManager.getConnection("jdbc:xmla:Server=http://" + WebAppConstants.BI_LINK_IP + "/MDKL/msmdpump.dll;Catalog=" + WebAppConstants.BI_LINK_NAME);
                wrapper = (OlapWrapper) con;
                olapConnection = wrapper.unwrap(OlapConnection.class);

                String startDateStr = startDate.toString();
                String endDateStr = endDate.toString();

                StringBuffer strBuffer = new StringBuffer();
                strBuffer.append(" ");
                strBuffer.append(" SELECT NON EMPTY { [Measures].[进], [Measures].[出] } ON 0, ");
                strBuffer.append("  {  [组织].[组织ID].[组织ID].ALLMEMBERS *  ");
                strBuffer.append(" [时间].[年].[年].ALLMEMBERS * ");
                strBuffer.append(" [时间].[月].[月].ALLMEMBERS *  ");
                strBuffer.append(" [时间].[日].[日].ALLMEMBERS * ");
                strBuffer.append(" [时间].[小时].[小时].ALLMEMBERS } on 1 ");
                strBuffer.append(" FROM ( SELECT ( { [时间].[年月日小时].[小时].&[" + startDate + "T00:00:00]:[时间].[年月日小时].[小时].&[" + endDate + "T00:00:00]},{ ");
                strBuffer.append("  [组织].[组织层次].&[" + shopId + "]  ");
                strBuffer.append(" } ) ON COLUMNS ");
                strBuffer.append(" FROM [客流]) ");


                stmt = olapConnection.createStatement();

                cellSet = stmt.executeOlapQuery(strBuffer.toString());

                for (Position rowPos : cellSet.getAxes().get(1)) {
                    String s = "";
                    for (Member member : rowPos.getMembers()) {
                        s += member.getCaption() + "*";
                    }
                    for (Position colPos : cellSet.getAxes().get(0)) {
                        Cell cell = cellSet.getCell(colPos, rowPos);
                        s += cell.getFormattedValue() + "*";
                    }
                    String[] ss = s.split("\\*");

                    String id = ss[0] + "-" + ss[1] + ss[2] + ss[3] + ss[4];
                    SissDataEntity sde = new SissDataEntity();

//                    sde.setId(id);
                    sde.setCode(id);
                    sde.setShopId(shopId);
                    sde.setShopCode(shopCode);
                    try {
                        sde.setDatetime(ss[1] + ss[2] + ss[3] + ss[4] + "0000");
                    } catch (Exception e) {
                        e.printStackTrace();
                        logger.info("~~~~~~~~~~33333333333333333~~~~~~~~~~~~~~~~~~");
                        sde.setDatetime("19700101000000");
                    }
                    sde.setConsumeFlag("0");
                    if (ss.length < 6) {
                        sde.setCnt("0");
                    } else {
                        sde.setCnt(ss[5]);
                        try {
                            sissService.saveInfo(sde, new Callback[]{idCallback});
                        } catch (Exception e) {
                            e.printStackTrace();
                            logger.info("~~~~~~~~~~4444444444444444444444~~~~~~~~~~~~~~~~~~");
                        }
                    }
                }

            } catch (Exception e) {
                logger.info("~~~~~~~~~~1111111111111111111~~~~~~~~~~~~~~~~~~");
                e.printStackTrace();
            } finally {
                end = startDate;
                if (end.compareTo(start) < 1) {
                    execFlag = false;
                }
                try {
                    if (cellSet != null) {
                        cellSet.close();
                    }
                    if (stmt != null) {
                        stmt.close();
                    }
                    if (olapConnection != null) {
                        olapConnection.close();
                    }
                    if (con != null) {
                        con.close();
                    }
                    Thread.currentThread().sleep(500);//毫秒
                } catch (Exception e) {
                    logger.info("~~~~~~~~~~22222222222222222~~~~~~~~~~~~~~~~~~");
                    e.printStackTrace();
                }
            }
        }
        logger.info("--end statisticsSiss job-- ");

    }

    /**
     * 检查更新设备状态(包括老设备和新设备)
     */
    @Override
    public void syncDeviceStatus() {

        long startTime = System.currentTimeMillis();
        logger.info("~~~" + LocalDateTime.now().toString() + "开始检查更新设备状态~~~");

        DeviceEntity condForNew = new DeviceEntity();
        condForNew.getProperties().put("type", "dtk3");
//        condForNew.getProperties().put("code", "12CE20D6");
        List<DeviceEntity> allDeviceList = deviceService.listAll(condForNew);
        logger.info("~~~新设备待同步状态共 "+allDeviceList.size()+" 台~~~");
        allDeviceList.forEach(device -> {
            Integer status = checkDeviceStatus(device);
            if (!Objects.equals(device.getStatus(), status)) {
                device.setStatus(status);
                deviceService.saveInfo(device);
            }
        });

        StringBuilder cntStrBuilder = new StringBuilder("");
        cntStrBuilder.append(" select count(1)");
        cntStrBuilder.append(" from [shopcusrec].[dbo].t_condition_info device,[shopcusrec].[dbo].[t_gprs_register] shop ");
        cntStrBuilder.append(" where device.module_no = shop.module_no ");
        Integer count = jdbcTemplate.queryForObject(cntStrBuilder.toString(), Integer.class);
        logger.info("~~~老设备待同步状态共 "+count+" 台~~~");
        StringBuilder strBuilder = new StringBuilder("");
        strBuilder.append(" select ");
        strBuilder.append(" device.id, "); //设备code
        strBuilder.append(" device.info, "); //设备位置
        strBuilder.append(" device.module_no, "); //门店code
        strBuilder.append(" shop.Last_ScanTime, "); //最后联机时间
        strBuilder.append(" device.losefocus, "); //是否失焦
        strBuilder.append(" device.batteryC, "); //剩余电量
        strBuilder.append(" device.batteryS, "); //剩余电量
        strBuilder.append(" shop.ischarge, "); //是否充电
        strBuilder.append(" device.direction, "); //安装方向
        strBuilder.append(" shop.islink "); //无线接收终端连接状态
        strBuilder.append(" from [shopcusrec].[dbo].t_condition_info device,[shopcusrec].[dbo].[t_gprs_register] shop ");
        strBuilder.append(" where device.module_no = shop.module_no ");

//        strBuilder.append(" and device.id in (3437, 3526) ");

        jdbcTemplate.queryForList(strBuilder.toString()).forEach(item -> {
            try {
                String deviceId = String.valueOf(item.get("id").toString());
                DeviceEntity condForOld = new DeviceEntity();
                condForOld.getProperties().put("code", deviceId);
                List<DeviceEntity> deviceList = deviceService.listAll(condForOld);
                if (deviceList != null && deviceList.size() > 0) {
                    DeviceEntity device = deviceList.get(0);
                    Integer paramFocus = item.get("losefocus") == null ?
                            0 : Integer.valueOf(item.get("losefocus").toString());
                    Long paramLastReceiveTime = item.get("Last_ScanTime") == null ?
                            0 : BreezeeUtils.DATE_FORMAT_LONG.parse(item.get("Last_ScanTime").toString()).getTime();

                    BigDecimal batteryC = item.get("batteryC") == null ? BigDecimal.ZERO : new BigDecimal(item.get("batteryC").toString());
                    BigDecimal batteryS = item.get("batteryS") == null ? BigDecimal.ZERO : new BigDecimal(item.get("batteryS").toString());

                    Integer paramVoltage = 0;
                    if (batteryC.compareTo(batteryS) > 0) {
                        paramVoltage = batteryS.divide(new BigDecimal(117), 4, BigDecimal.ROUND_HALF_UP)
                                .multiply(new BigDecimal(100)).intValue();
                    } else {
                        paramVoltage = batteryC.divide(new BigDecimal(117), 4, BigDecimal.ROUND_HALF_UP)
                                .multiply(new BigDecimal(100)).intValue();
                    }
//                    Integer paramVoltage = item.get("lastbat") == null ?
//                            0 : Integer.valueOf(item.get("lastbat").toString());

                    if (paramFocus.equals(device.getFocus())
                            && paramLastReceiveTime.equals(device.getLastReceiveTime())
                            && paramVoltage.equals(device.getVoltage())) {
                        Integer status = checkDeviceStatus(device);
                        if (!Objects.equals(device.getStatus(), status)) {
                            device.setStatus(status);
                            deviceService.saveInfo(device);
                        }
                    } else {
                        device.setFocus(paramFocus);
                        device.setLastReceiveTime(paramLastReceiveTime);
                        device.setVoltage(paramVoltage);
                        Integer status = checkDeviceStatus(device);
                        device.setStatus(status);
                        deviceService.saveInfo(device);
                    }
                }
            } catch (ParseException e) {
                logger.info(e.getMessage());
                e.printStackTrace();
            }
        });

        long endTime = System.currentTimeMillis();
        logger.info("~~~检查更新设备状态结束，本次共耗时： " + (endTime - startTime) + "ms~~~~~~");
    }


    /**
     * 检查更新我们的新设备的状态
     * TODO 该方法暂时不用，合并到新方法syncDeviceStatus中
     */
    @Override
    public void checkNewDeviceStatus() {

        logger.info("检查更新新设备状态开始...");

        DeviceEntity condition = new DeviceEntity();
        condition.getProperties().put("type", "dtk3");
        List<DeviceEntity> allDeviceList = deviceService.listAll(condition);

        allDeviceList.forEach(device -> {
            Integer status = checkDeviceStatus(device);
            if (!Objects.equals(device.getStatus(), status)) {
                device.setStatus(status);
                deviceService.saveInfo(device);
            }
        });

        logger.info("检查更新新设备状态结束...");
    }

    /**
     * 定时同步老设备状态
     * 从t_condition_info , t_gprs_register 同步状态
     * TODO 该方法暂时不用，合并到新方法syncDeviceStatus中
     */
    @Override
    public void syncOldStatus() {

        logger.info("同步老设备状态开始...");
        StringBuilder strBuilder = new StringBuilder("");
        strBuilder.append(" select ");
        strBuilder.append(" device.id, "); //设备code
        strBuilder.append(" device.info, "); //设备位置
        strBuilder.append(" device.module_no, "); //门店code
        strBuilder.append(" shop.Last_ScanTime, "); //最后联机时间
        strBuilder.append(" device.losefocus, "); //是否失焦
        strBuilder.append(" device.batteryC, "); //剩余电量
        strBuilder.append(" device.batteryS, "); //剩余电量
        strBuilder.append(" shop.ischarge, "); //是否充电
        strBuilder.append(" device.direction, "); //安装方向
        strBuilder.append(" shop.islink "); //无线接收终端连接状态
        strBuilder.append(" from [shopcusrec].[dbo].t_condition_info device,[shopcusrec].[dbo].[t_gprs_register] shop ");
        strBuilder.append(" where device.module_no = shop.module_no ");
//        strBuilder.append(" and device.id in ('3577') ");

        jdbcTemplate.queryForList(strBuilder.toString()).forEach(item -> {
            try {
                String deviceId = String.valueOf(item.get("id").toString());
                DeviceEntity condition = new DeviceEntity();
                condition.getProperties().put("code", deviceId);
                List<DeviceEntity> deviceList = deviceService.listAll(condition);
                if (deviceList != null && deviceList.size() > 0) {
                    DeviceEntity device = deviceList.get(0);
                    Integer paramFocus = item.get("losefocus") == null ?
                            0 : Integer.valueOf(item.get("losefocus").toString());
                    Long paramLastReceiveTime = item.get("Last_ScanTime") == null ?
                            0 : BreezeeUtils.DATE_FORMAT_LONG.parse(item.get("Last_ScanTime").toString()).getTime();

                    BigDecimal batteryC = item.get("batteryC") == null ? BigDecimal.ZERO : new BigDecimal(item.get("batteryC").toString());
                    BigDecimal batteryS = item.get("batteryS") == null ? BigDecimal.ZERO : new BigDecimal(item.get("batteryS").toString());

                    Integer paramVoltage = 0;
                    if (batteryC.compareTo(batteryS) > 0) {
                        paramVoltage = batteryS.divide(new BigDecimal(117), 4, BigDecimal.ROUND_HALF_UP)
                                .multiply(new BigDecimal(100)).intValue();
                    } else {
                        paramVoltage = batteryC.divide(new BigDecimal(117), 4, BigDecimal.ROUND_HALF_UP)
                                .multiply(new BigDecimal(100)).intValue();
                    }
//                    Integer paramVoltage = item.get("lastbat") == null ?
//                            0 : Integer.valueOf(item.get("lastbat").toString());

                    if (paramFocus.equals(device.getFocus())
                            && paramLastReceiveTime.equals(device.getLastReceiveTime())
                            && paramVoltage.equals(device.getVoltage())) {
                        Integer status = checkDeviceStatus(device);
                        if (!Objects.equals(device.getStatus(), status)) {
                            device.setStatus(status);
                            deviceService.saveInfo(device);
                        }
                    } else {
                        device.setFocus(paramFocus);
                        device.setLastReceiveTime(paramLastReceiveTime);
                        device.setVoltage(paramVoltage);
                        Integer status = checkDeviceStatus(device);
                        device.setStatus(status);
                        deviceService.saveInfo(device);
                    }
                }
            } catch (ParseException e) {
                e.printStackTrace();
            }
        });
        logger.info("同步老设备状态结束...");

    }


    /**
     * 每天一次，检查更新门店状态，主要是根据开店关店时间，判断门店是未开店还是已撤店
     */
    @Override
    public void checkShopStatus() {

        logger.info("检查更新门店状态开始...");
        CustomerEntity condition = new CustomerEntity();
        condition.getProperties().put("category", "3");
        List<CustomerEntity> shopList = customerService.listAll(condition);

        shopList.forEach(shop -> {
            Integer status = shop.getStatus();
            LocalDateTime now = LocalDateTime.now();
            if (shop.getOpenDate() != null) {
                LocalDateTime openDateTime = LocalDateTime
                        .ofInstant(shop.getOpenDate().toInstant(), ZoneId.systemDefault());
                if (now.compareTo(openDateTime) < 0) {
                    status = ShopStatusEnum.UNINSTALLED.getValue();
                } else {
                    if (Objects.equals(shop.getStatus(), ShopStatusEnum.UNINSTALLED)) {
                        status = ShopStatusEnum.ENABLE.getValue();
                    }
                }
            }
            if (shop.getCloseDate() != null) {
                LocalDateTime closeDateTime = LocalDateTime
                        .ofInstant(shop.getCloseDate().toInstant(), ZoneId.systemDefault());
                if (now.compareTo(closeDateTime) > 0) {
                    status = ShopStatusEnum.SHUTDOWN.getValue();
                }
            }

            if (status != null) {
                shop.setStatus(status);
                customerService.saveInfo(shop);
            }
        });

        logger.info("检查更新门店状态结束...");
    }

    /**
     * 检查更新设备状态
     *
     * @param device
     * @return
     */
    private Integer checkDeviceStatus(DeviceEntity device) {

        Integer status = DeviceStatusEnum.ENABLE.getValue();
        Long last = device.getLastReceiveTime();
        Long now = System.currentTimeMillis();

        int nowHour = LocalDateTime.now().getHour();
        //是否有最后数据上传时间
        if (last == null) {
            status = DeviceStatusEnum.UNKNOWN.getValue();
        } else {
            //如果在营业时间内，超过三个采集周期没有连接，则离线
            //FIXME 营业时间写死了9~22，时间2小时，后面可能需要修改
            if (nowHour > 8 && nowHour < 23) {
                if ((now - last) > (120 * 60 * 1000)) {
                    status = DeviceStatusEnum.UNKNOWN.getValue();
                } else if (device.getFocus() == null || Objects.equals(device.getFocus(), 1)) {
                    status = DeviceStatusEnum.DISABLE.getValue();
                } else if (device.getVoltage() == null || device.getVoltage().intValue() < 10) {
                    status = DeviceStatusEnum.DISABLE.getValue();
                }
            } else {
                status = device.getStatus();
            }
        }
        return status;

    }

}
